
from demo import models
from demo import serializers
import json

# 类视图
from django.shortcuts import render
from django.views import View
from django.http import HttpResponse, JsonResponse

"""
1 没有使用DRF视图，使用的是django原生视图View
2 使用了DRF序列化器，序列号器的作用：减少了模型，字典，JSON之间的转换代码

Serializer的构造方法为：
Serializer(instance=None, data=empty, **kwarg)
使用：
1）用于序列化时，将模型类对象传入instance参数
2）用于反序列化时，将要被反序列化的数据传入data参数


配置步骤：
查（列表视图）
1 查询出所有图书模型，得到一个查询集。
2 调用序列化器，进行序列化，要传入查询集。
3 响应，将python字典转换成JSON格式。

增（列表视图）
1 使用request参数接前端数据总是报错，所以这里自定义一个JSON_Str数据。
2 把JSON_Bytes 转换成 JSON_Str(String类型的JSON数据)。
3 利用 Json模块 json.loads 将 JSON_Str 转换成 python字典。
4 创建模型对象，把 python字典 转换成 django模型，并保存。
5 再将 新增的django模型 转换为 python字典。
6 响应，将python字典转换成JSON格式，响应码201。

"""

class BookSerializerListView(View):
    # 序列化 列表视图
    def get(self, request):
        # 1 查询出所有图书模型，得到一个查询集。
        book = models.Book.objects.all()

        # 2 调用序列化器，进行序列化，要传入查询集。
        s = serializers.BookSerializer(book, many=True)
        print(s.data)  # 返回的是一个有序字典

        return JsonResponse(s.data, safe=False)

    # 反序列化 列表视图
    def post(self, request):
        # 1 使用request参数接前端数据总是报错，所以这里自定义一个JSON_Str数据。
        data = {
            "bookname": "hello 降龙十八掌 123",
            "price": "48 123"
        }

        # 2 调用序列化器，传入JSON_Str数据
        req = serializers.BookSerializer(data=data)
        print(req)
        """
        BookSerializer(data={'bookname': 'hello 降龙十八掌 123', 'price': '48 123'}):
            id = IntegerField(label='ID', read_only=True)
            bookname = CharField(label='书名', required=True)
            price = CharField(label='价格', required=True)    
        """

        # 走校验逻辑，判断模型类型，判断选项，返回bool类型
        b = req.is_valid()
        print(b)
        """
        True
        """
        # 或者req.is_valid(rasie_exception=True)，校验出错后会自动抛出异常。

        # 获得数据
        c = req.validated_data
        print(c)
        """
        .validated_data获得一个有序字典
        OrderedDict([('bookname', 'hello 降龙十八掌 123'), ('price', '48 123')])
        """

        # 当调用序列化器的save方法时，会执行序列化器的create方法或者update方法
        # 源码分析，在 D:\PycharmProjects\pythonenv\venv\Lib\site-packages\rest_framework\serializers.py
        '''
        class BaseSerializer(Field):
            def __init__(self, instance=None, data=empty, **kwargs):
                self.instance = instance

            def save(self, **kwargs):
                if self.instance is not None:
                    self.instance = self.update(self.instance, validated_data)
                    assert self.instance is not None, (
                        '`update()` did not return an object instance.'
                    )
                else:
                    self.instance = self.create(validated_data)
                    assert self.instance is not None, (
                        '`create()` did not return an object instance.'
                    )
            return self.instance

        可是我们发现，self.update和self.create中，源码是没有action，需要我们在序列化器中自己定义：
        
        def update(self, instance, validated_data):
            raise NotImplementedError('`update()` must be implemented.')
    
        def create(self, validated_data):
            raise NotImplementedError('`create()` must be implemented.')
        
        所以在Serializers中我们在 BookSerializer 序列化器中自定义了update和create方法
        '''
        req.save()

        # 注意，这里反序列化 的同时，还做 了序列化，同样可以调用data
        print(req.data)
        """
        返回了python字典
        {'bookname': 'hello 降龙十八掌 123', 'price': '48 123'}
        """
        return JsonResponse(req.data)


class BookSerializerDetailView(View):
    def get(self, request, pk):

        book = models.Book.objects.get(id=pk)

        s = serializers.BookSerializer(instance=book)
        print(s.data)

        return JsonResponse(s.data)

    def put(self, request, pk):

        data = {
            "bookname": "降龙十八掌hello",
            "price": "48123"
        }

        book = models.Book.objects.get(id=pk)

        req = serializers.BookSerializer(instance=book, data=data)
        return HttpResponse('123')

    def delete(self, request, pk):
        pass